package com.sangeng.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.sangeng.domain.dto.UserInfoDTO;
import com.sangeng.domain.entity.user.LoginUser;
import com.sangeng.domain.entity.user.User;
import com.sangeng.domain.vo.UserInfoVO;
import com.sangeng.mapper.PermissionMapper;
import com.sangeng.service.LoginService;
import com.sangeng.utils.JwtUtil;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.sangeng.constant.RedisConst.*;

@Service
public class LoginServiceImpl implements LoginService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private AuthenticationManager authenticationManager;
    @Resource
    private PermissionMapper permissionMapper;

    @Override
    public String login(UserInfoDTO userInfoDTO) {
        //AuthenticationManager authenticate用户认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userInfoDTO.getUsername(), userInfoDTO.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //如果认证没通过，给出对应的提示
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("登录失败");
        }
        //如果认证通过，生成jwt token
        LoginUser loginUser = (LoginUser)authenticate.getPrincipal();
        Long userId = loginUser.getUser().getId();
        Map<String,Object> map = new HashMap<>();
        map.put("username",userInfoDTO.getUsername());
        map.put("password",userInfoDTO.getPassword());
        map.put("userId",userId);
        String token = JwtUtil.createJwt(map);
        //把完整的用户信息存入redis，userId作为key
        stringRedisTemplate.opsForValue().set(USER_LOGIN_INFO + userId, JSON.toJSONString(loginUser),1, TimeUnit.HOURS);
        stringRedisTemplate.opsForValue().set(USER_LOGIN_TOKEN + userId,token,1, TimeUnit.HOURS);
        return token;
    }

    /**
     * 用户登出
     */
    @Override
    public void logout() {
        //把用户信息和token从redis中删除
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser)authentication.getPrincipal();
        Long userId = loginUser.getUser().getId();
        stringRedisTemplate.delete(USER_LOGIN_INFO + userId);
        stringRedisTemplate.delete(USER_LOGIN_TOKEN + userId);
    }

    /**
     * 获取用户信息
     */
    @Override
    public UserInfoVO getUserInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser)authentication.getPrincipal();
        User user = loginUser.getUser();
        //查询用户的路由权限
        List<String> routes = permissionMapper.getPermissionCode(user.getId());
        return new UserInfoVO(user.getUserName(),user.getAvatar(),routes);
    }
}
